iT邦幫忙

2023 iThome 鐵人賽

DAY 11
0
自我挑戰組

JS 加強筆記系列 第 11

Day 11:錯誤處理

  • 分享至 

  • xImage
  •  

promise 鏈中出現錯誤時,會順著鏈接去到最近的錯誤處理函式。也可以說最簡單的處理方式就是在鏈接的尾端加上 catch,來抓所有錯誤,很類似一般的 try...catch 結構:

doSomething()
  .then((result) => doSomethingElse(result))
  .then((newResult) => doThirdThing(newResult))
  .then((finalResult) => console.log(`Got the final result: ${finalResult}`))
  .catch(failureCallback);

promise executor 或各處理函式中只要出現錯誤,無論是 promise 本身失敗、丟出例外或程式錯誤,都會有如同 rejected promise 的表現,可以在 catch 中接到處理。例如以下兩段會得到一樣的錯誤:

// 1
new Promise((resolve, reject) => {
    throw new Error('Whoops!');
}).catch(alert); // Error: Whoops!

// 2
new Promise((resolve, reject) => {
    reject(new Error('Whoops!'));
}).catch(alert); // Error: Whoops!

如果沒有處理,發生錯誤會造成程式中斷。這時候瀏覽器的 JS 引擎會產生一個全域錯誤,可以用 'unhandledrejection' 事件追蹤到,這段有更詳細的範例解說。

巢狀與錯誤處理

程式碼要不要巢狀撰寫除了可讀性和個人習慣外,也可以考慮這種結構會造成的實際影響。這部分可參考前一篇最後一個例子。

巢狀的一個效果是會限制 catch 的作用範圍,它變成只會抓到內層的錯誤,善加運用這點可以做到更精確的錯誤處理:

doSomethingCritical()
    .then((result) =>
        doSomethingOptional(result)
            .then((optionalResult) => doSomethingExtra(optionalResult))
            .catch((e) => {}),  // 第 5 行
        ) 
    // 無論 doSomethingOptional 成功失敗都會進行
    .then(() => moreCriticalStuff())
    .catch((e) => console.error(`Critical failure: ${e.message}`));

這樣的結構有一些特性

  • 第五行寫在內層的 catch 只會處理 doSomethingOptionaldoSomethingExtra 的錯誤。並且有處理後錯誤自然就不會再跑到外面去。
  • 巢狀的部分像是開了另外一條支線,不管有沒有出錯都不會影響外層程式碼的進行。所以像這段虛擬碼的函式語意,內層可以用來放額外多做、不影響正事的事情。
  • 承上,也因為這樣結構讓錯誤處理有「分流」的效果,如果是無意或非必要的巢狀可能會導致錯誤漏接。

一般而言,最佳做法是盡量不要有巢狀,鏈接越平越好,但必要時也可以利用結構來做適當的程式碼控制。


上一篇
Day 10:務必回傳 promise
下一篇
Day 12:錯誤處理實例
系列文
JS 加強筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言